package Controller

import (
	"back_go/DAO"
	models "back_go/DAO/model"
	"back_go/Middleware"
	"back_go/Response"
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/minio/minio-go/v7"
	"io"
	"net/http"
	"path/filepath"
	"time"
)

// UploadFileController 文件上传
/*

	@file 文件
	@return string 文件名
*/
func UploadFileController(c *gin.Context) {
	var engine = DAO.Engine
	var fileDb models.Images

	// 单文件上传
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 生成 UUID 作为文件名
	uuid1 := uuid.New()
	filename := uuid1.String() + filepath.Ext(file.Filename)

	fileDb.Filename = filename
	fileDb.UploadTime = time.Now()

	// 打开上传的文件
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer src.Close()

	// 将文件保存到 MinIO
	_, err = Middleware.MinioClient.PutObject(context.Background(), "admin-file", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	_, err = Middleware.MinioClient.PutObject(context.Background(), "admin-file", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	minioPath := fmt.Sprintf("admin-file\\%s", filename)
	fileDb.Path = minioPath
	_, err = engine.Insert(&fileDb)
	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       nil,
		Data:      fileDb.Filename,
		Version:   "v1.0",
		Timestamp: time.Now().Unix(),
		Sign:      nil,
		Success:   true,
		Fail:      false,
	})
}

// GetAdminFile 获取文件
/*

	@fileName 文件名
	@return 文件
*/
func GetAdminFile(c *gin.Context) {
	fileName := c.Param("fileName")

	// 使用特定的命名空间（如"cache"）加上文件名作为 Redis 的键
	cacheKey := "cache/" + fileName

	// 尝试从 Redis 中获取文件内容
	cachedContent, err := Middleware.RedisClient.Get(c, cacheKey).Bytes()
	if err == nil {
		// 设置响应头，以便浏览器可以正确处理下载
		c.Header("Content-Disposition", "attachment; filename="+fileName)
		c.Header("Content-Type", "application/octet-stream")
		c.Writer.Write(cachedContent)
		return
	}

	object, err := Middleware.MinioClient.GetObject(context.Background(), "admin-file", fileName, minio.GetObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer object.Close()

	// 设置响应头，以便浏览器可以正确处理下载
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")

	fileContent, err := io.ReadAll(object)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 设置过期时间为 1 小时（3600 秒）
	expiration := 1 * time.Hour
	err = Middleware.RedisClient.Set(c, cacheKey, fileContent, expiration).Err()
	if err != nil {
		println("Failed to cache file in Redis:", err.Error())
	}

	// 直接将从 MinIO 读取的内容写入响应
	_, err = c.Writer.Write(fileContent)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
}

// UploadIndexImg 上传首页图片
/*

	@file 文件
	@return string 文件名
*/
func UploadIndexImg(c *gin.Context) {
	var engine = DAO.Engine
	var fileDb models.Images

	// 单文件上传
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 生成 UUID 作为文件名
	uuid1 := uuid.New()
	filename := uuid1.String() + filepath.Ext(file.Filename)

	fileDb.Filename = filename
	fileDb.UploadTime = time.Now()

	// 打开上传的文件
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer src.Close()

	// 将文件保存到 MinIO
	_, err = Middleware.MinioClient.PutObject(context.Background(), "indeximg", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	_, err = Middleware.MinioClient.PutObject(context.Background(), "indeximg", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	minioPath := fmt.Sprintf("indeximg\\%s", filename)
	fileDb.Path = minioPath
	_, err = engine.Insert(&fileDb)
	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       nil,
		Data:      "http://localhost:8080/indexImg/" + fileDb.Filename,
		Version:   "v1.0",
		Timestamp: time.Now().Unix(),
		Sign:      nil,
		Success:   true,
		Fail:      false,
	})
}

/*
UploadUserImg
@description: 上传用户头像
*/
func UploadUserImg(c *gin.Context) {
	// 单文件上传
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 生成 UUID 作为文件名
	uuid1 := uuid.New()
	filename := uuid1.String() + filepath.Ext(file.Filename)

	// 打开上传的文件
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer src.Close()

	// 将文件保存到 MinIO
	_, err = Middleware.MinioClient.PutObject(context.Background(), "useravatar", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	_, err = Middleware.MinioClient.PutObject(context.Background(), "useravatar", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	//minioPath := fmt.Sprintf("userAvatar\\%s", filename)

	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       nil,
		Data:      "http://localhost:8080/useravatar/" + filename,
		Version:   "v1.0",
		Timestamp: time.Now().Unix(),
		Sign:      nil,
		Success:   true,
		Fail:      false,
	})
}

/*
UploadEvaluate
@description: 上传评价图片
*/
func UploadEvaluate(c *gin.Context) {
	// 单文件上传
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 生成 UUID 作为文件名
	uuid1 := uuid.New()
	filename := uuid1.String() + filepath.Ext(file.Filename)

	// 打开上传的文件
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer src.Close()

	// 将文件保存到 MinIO
	_, err = Middleware.MinioClient.PutObject(context.Background(), "evaluate", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	_, err = Middleware.MinioClient.PutObject(context.Background(), "evaluate", filename, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	//minioPath := fmt.Sprintf("evaluate\\%s", filename)

	c.JSON(http.StatusOK, Response.ResponseBody{
		Code:      "00000",
		Msg:       nil,
		Data:      "http://localhost:8080/evaluate/" + filename,
		Version:   "v1.0",
		Timestamp: time.Now().Unix(),
		Sign:      nil,
		Success:   true,
		Fail:      false,
	})
}

// GetIndexImgFile 获取首页图片
/*

	@fileName 文件名
	@return 文件
*/
func GetIndexImgFile(c *gin.Context) {
	fileName := c.Param("fileName")

	// 使用特定的命名空间（如"cache"）加上文件名作为 Redis 的键
	cacheKey := "cache/" + fileName

	// 尝试从 Redis 中获取文件内容
	cachedContent, err := Middleware.RedisClient.Get(c, cacheKey).Bytes()
	if err == nil {
		// 设置响应头，以便浏览器可以正确处理下载
		c.Header("Content-Disposition", "attachment; filename="+fileName)
		c.Header("Content-Type", "application/octet-stream")
		c.Writer.Write(cachedContent)
		return
	}

	object, err := Middleware.MinioClient.GetObject(context.Background(), "indeximg", fileName, minio.GetObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer object.Close()

	// 设置响应头，以便浏览器可以正确处理下载
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")

	fileContent, err := io.ReadAll(object)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 设置过期时间为 1 小时（3600 秒）
	expiration := 1 * time.Hour
	err = Middleware.RedisClient.Set(c, cacheKey, fileContent, expiration).Err()
	if err != nil {
		println("Failed to cache file in Redis:", err.Error())
	}

	// 直接将从 MinIO 读取的内容写入响应
	_, err = c.Writer.Write(fileContent)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
}

/*
GetUserAvatar
@description: 获取用户头像
*/
func GetUserAvatar(c *gin.Context) {
	fileName := c.Param("fileName")

	// 使用特定的命名空间（如"cache"）加上文件名作为 Redis 的键
	cacheKey := "cacheAvatar/" + fileName

	// 尝试从 Redis 中获取文件内容
	cachedContent, err := Middleware.RedisClient.Get(c, cacheKey).Bytes()
	if err == nil {
		// 设置响应头，以便浏览器可以正确处理下载
		c.Header("Content-Disposition", "attachment; filename="+fileName)
		c.Header("Content-Type", "application/octet-stream")
		c.Writer.Write(cachedContent)
		return
	}

	object, err := Middleware.MinioClient.GetObject(context.Background(), "useravatar", fileName, minio.GetObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer object.Close()

	// 设置响应头，以便浏览器可以正确处理下载
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")

	fileContent, err := io.ReadAll(object)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 设置过期时间为 1 小时（3600 秒）
	expiration := 1 * time.Hour
	err = Middleware.RedisClient.Set(c, cacheKey, fileContent, expiration).Err()
	if err != nil {
		println("Failed to cache file in Redis:", err.Error())
	}

	// 直接将从 MinIO 读取的内容写入响应
	_, err = c.Writer.Write(fileContent)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
}

func GetEvaluate(c *gin.Context) {
	fileName := c.Param("fileName")

	// 使用特定的命名空间（如"cache"）加上文件名作为 Redis 的键
	cacheKey := "cacheEvaluate/" + fileName

	// 尝试从 Redis 中获取文件内容
	cachedContent, err := Middleware.RedisClient.Get(c, cacheKey).Bytes()
	if err == nil {
		// 设置响应头，以便浏览器可以正确处理下载
		c.Header("Content-Disposition", "attachment; filename="+fileName)
		c.Header("Content-Type", "application/octet-stream")
		c.Writer.Write(cachedContent)
		return
	}

	object, err := Middleware.MinioClient.GetObject(context.Background(), "evaluate", fileName, minio.GetObjectOptions{})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	defer object.Close()

	// 设置响应头，以便浏览器可以正确处理下载
	c.Header("Content-Disposition", "attachment; filename="+fileName)
	c.Header("Content-Type", "application/octet-stream")

	fileContent, err := io.ReadAll(object)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 设置过期时间为 1 小时（3600 秒）
	expiration := 1 * time.Hour
	err = Middleware.RedisClient.Set(c, cacheKey, fileContent, expiration).Err()
	if err != nil {
		println("Failed to cache file in Redis:", err.Error())
	}

	// 直接将从 MinIO 读取的内容写入响应
	_, err = c.Writer.Write(fileContent)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
}
